#!/usr/bin/env python

__author__ = "Abhinav Sarkar"
__version__ = "0.1"
__license__ = "GNU Lesser General Public License"

class Group (object):
	"""A class representing a group.
	
	The Group class exposes the following instance properties:
	
		 group.name
		 group.recentWeeklyAlbumChart
		 group.recentWeeklyArtistChart
		 group.recentWeeklyTrackChart
		 
	The Group class exposes the following instance methods:
		
		group.GetWeeklyAlbumChart(start, end)
		group.GetWeeklyAlbumChartList()
		group.GetWeeklyArtistChart(start, end)
		group.GetWeeklyArtistChartList()
		group.GetWeeklyTrackChart(start, end)
		group.GetWeeklyTrackChartList()
	"""
	def __init__(self, name):
		"""An object to hold a group.
		
		This class is normally instantiated by the Webservice class.
		
		Args:
			name: name of this group
			
		Usage:
			>>> import audioscrobblerws
			>>> ws = audioscrobblerws.Webservice()
			>>> group = ws.GetGroup('rhythmbox')
		"""
		self.name = name

	def GetWeeklyChart(self, kind, start = None, end = None):
		"""Get weekly chart for this group.

		This method is not meant to be called directly. Use group.GetWeeklyArtistChart(),
		group.GetWeeklyAlbumChart() and group.GetWeeklyTrackChart() instead.

		Args:
			kind: type of the weekly chart to fetch. can be 'artist', 'album' or 'track'.
			start:
				time for the start of the chart. can be datetime.datetime object
				or a unix timestamp. (default: None)
			end:
				time for the end of the chart. can be datetime.datetime object
				or a unix timestamp. (default: None)

		Returns:
			A WeeklyArtistChart, WeeklyAlbumChart or WeeklyTrackChart object depending
			upon the 'kind' provided.
		"""

		if not self.name:
			raise AudioscrobblerError("group name has to be set before calling this method")
		return eval("Weekly" + kind.title() + "Chart")(
			group = self.name,
			start = start,
			end = end
		)

	def GetWeeklyArtistChart(self, start = None, end = None):
		"""Get weekly artist chart for this group.
		
		Args:
			start:
				time for the start of the chart. can be datetime.datetime object
				or a unix timestamp. (default: None)
			end:
				time for the end of the chart. can be datetime.datetime object
				or a unix timestamp. (default: None)

		Returns:
			A WeeklyArtistChart object. If 'start' and 'end' are not provided then
			the chart for the most recent week is returned. Else the chart for the
			specified week is returned.

		Usage:
			>>> group = ws.GetGroup('rhythmbox')
			>>> wac = group.GetWeeklyArtistChart()
			>>> wac.start
			datetime.datetime(2008, 6, 8, 17, 30)
			>>> wac.end
			datetime.datetime(2008, 6, 15, 17, 30)
			>>> [(a.name, a.reach) for a in wac.artists[:10]]
			[('Radiohead', 368), ('Coldplay', 346), ('The Beatles', 321), ('Pink Floyd', 301), 
			('Nine Inch Nails', 273), ('Metallica', 273), ('Red Hot Chili Peppers', 271), 
			('Nirvana', 271), ('Queen', 256), ('U2', 245)]
		"""
		return self.GetWeeklyChart("artist", start, end)

	recentWeeklyArtistChart = property(GetWeeklyArtistChart,
		doc = "Weekly artist chart of the most recent week for this group")
	
	def GetWeeklyAlbumChart(self, start = None, end = None):
		"""Get weekly album chart for this group.
		
		Args:
			start:
				time for the start of the chart. can be datetime.datetime object
				or a unix timestamp. (default: None)
			end:
				time for the end of the chart. can be datetime.datetime object
				or a unix timestamp. (default: None)

		Returns:
			A WeeklyAlbumChart object. If 'start' and 'end' are not provided then
			the chart for the most recent week is returned. Else the chart for the
			specified week is returned.

		Usage:
			>>> group = ws.GetGroup('rhythmbox')
			>>> wac = group.GetWeeklyAlbumChart()
			>>> wac.start
			datetime.datetime(2008, 6, 8, 17, 30)
			>>> wac.end
			datetime.datetime(2008, 6, 15, 17, 30)
			>>> [(a.name, a.reach) for a in wac.albums[:10]]
			[('OK Computer', 117), ('Nevermind', 113), ('A Rush of Blood to the Head', 108), 
			('In Rainbows', 107), ('Discovery', 99), ('Meteora', 96), ('Demon Days', 95), 
			('Black Holes And Revelations', 94), ('Rage Against the Machine', 93), ('Toxicity', 93)]
		"""
		return self.GetWeeklyChart("album", start, end)

	recentWeeklyAlbumChart = property(GetWeeklyAlbumChart,
		doc = "Weekly album chart of the most recent week for this group")
	
	def GetWeeklyTrackChart(self, start = None, end = None):
		"""Get weekly track chart for this group.
		
		Args:
			start:
				time for the start of the chart. can be datetime.datetime object
				or a unix timestamp. (default: None)
			end:
				time for the end of the chart. can be datetime.datetime object
				or a unix timestamp. (default: None)

		Returns:
			A WeeklyTrackChart object. If 'start' and 'end' are not provided then
			the chart for the most recent week is returned. Else the chart for the
			specified week is returned.

		Usage:
			>>> group = ws.GetGroup('rhythmbox')
			>>> wtc = group.GetWeeklyTrackChart()
			>>> wtc.start
			datetime.datetime(2008, 6, 8, 17, 30)
			>>> wtc.end
			datetime.datetime(2008, 6, 15, 17, 30)
			>>> [(t.name, t.reach) for t in wtc.tracks[:10]]
			[('Violet Hill', 89), ('Viva La Vida', 87), ('42', 70), ('Life in Technicolor', 67), 
			('Cemeteries of London', 67), ('Stairway to Heaven', 60), ('Strawberry Swing', 59), 
			('Nude', 55), ('Knights of Cydonia', 54), ('Come as You Are', 53)]
		"""
		return self.GetWeeklyChart("track", start, end)

	recentWeeklyTrackChart = property(GetWeeklyTrackChart,
		doc = "Weekly track chart of the most recent week for this group")

	def GetWeeklyChartList(self, kind = None):
		"""Get list of weekly charts of all weeks for this group.
		
		Args:
			kind:
				type of chart to fetch. can be 'artist', 'album' or 'track'.
				(default: None)

		Returns:
			An ordered list of WeeklyArtistChart, WeeklyAlbumChart or WeeklyTrackChart objects
			depending upon the 'kind' provided. If 'kind' is not provided then a
			list of WeeklyChart is returned.

		Usage:
		>>> group = ws.GetGroup('rhythmbox')
		>>> wcl = group.GetWeeklyChartList()
		>>> [(wc.start, wc.end) for wc in wcl[:3]]
		[(datetime.datetime(2006, 9, 24, 17, 30), datetime.datetime(2006, 10, 1, 17, 30)), 
		(datetime.datetime(2006, 10, 1, 17, 30), datetime.datetime(2006, 10, 8, 17, 30)), 
		(datetime.datetime(2006, 10, 8, 17, 30), datetime.datetime(2006, 10, 15, 17, 30))]
		"""
		if not self.name:
			raise AudioscrobblerError("group name has to be set before calling this method")

		url = "http://ws.audioscrobbler.com/1.0/group/%s/weeklychartlist.xml" % self.name
		xml = Webservice()._FetchUrl(url)
		data = Xml2Dict(ElementTree.XML(xml))

		weeklychartlist = []
		if not 'chart' in data:
			return weeklychartlist

		if kind != None:
			for chartData in data['chart']:
				try:
					weeklychartlist.append(
						eval("Weekly" + kind.title() + "Chart")(
							group = self.name,
							start = int(chartData['@from']),
							end = int(chartData['@to'])
						)
					)
				except SyntaxError:
					pass
		else:
			for chartData in data['chart']:
				weeklychartlist.append(
					WeeklyChart(
						group = self.name,
						start = int(chartData['@from']),
						end = int(chartData['@to'])
					)
				)

		return weeklychartlist

	def GetWeeklyArtistChartList(self):
		"""Get a list of all weekly artist charts of all weeks for this group.

		Returns:
			An ordered list of WeeklyArtistChart objects.
		"""
		return self.GetWeeklyChartList("artist")

	def GetWeeklyAlbumChartList(self):
		"""Get a list of all weekly album charts of all weeks for this group.

		Returns:
			An ordered list of WeeklyAlbumChart objects.
		"""
		return self.GetWeeklyChartList("album")

	def GetWeeklyTrackChartList(self):
		"""Get a list of all weekly track charts of all weeks for this group.

		Returns:
			An ordered list of WeeklyTrackChart objects.
		"""
		return self.GetWeeklyChartList("track")

	def __eq__(self, other):
		return self.name == other.name

	def __ne__(self, other):
		return not self.__eq__(other)
		
import cElementTree as ElementTree

from webservice import Webservice
from weeklychart import WeeklyChart, WeeklyArtistChart, WeeklyAlbumChart, WeeklyTrackChart
from xml2dict import Xml2Dict
from error import AudioscrobblerError